#include "luaMgr.h"

cLuaMgr gLuaMgr;

/*
============
CFunction
============
*/
static const luaL_Reg utilitylib[] = {
	{ "GetKeyState"		,	 GetKeyState		},
	{ "GetMouseState"	,	 GetMouseState		},
	{ "GetIntersectVec3",	 GetIntersectVec3	},
	{ "GetTerrainHeight",	 GetTerrainHeight	},
	{ NULL, NULL}
};

static int RegisterLib( lua_State* pL )
{
	luaL_register( pL, "utility", utilitylib );
	return 1;
}

static int GetKeyState( lua_State* pL )
{
	int virtualKey = lua_tointeger( pL, -1 );
	bool bRet = GetKeyState( virtualKey ) & 0x80;
	lua_pushboolean( pL, bRet );
	return 1;
}
static int GetMouseState( lua_State* pL )
{
	int mouse = lua_tointeger( pL, -1 );
	bool bRet = GetMouseState( mouse );
	lua_pushboolean( pL, bRet );
	return 1;
}
static int GetIntersectVec3( lua_State* pL )
{
	vector<cTerrainBase*> vecVisibleTerrain = GetVisibleTerrainTile();
	D3DXVECTOR3 intersectVec3;
	for( int i = 0; i != vecVisibleTerrain.size(); ++i )
	{
		if( GetIntersectVec3( vecVisibleTerrain[ i ]->GetMesh(), intersectVec3 ) )
		{
			break;
		}
	}

	PushVector( pL, intersectVec3 );
	return 1;
}

static int GetTerrainHeight( lua_State* pL )
{
	float z = lua_tointeger( pL, -1 );
	float x = lua_tointeger( pL, -2 );
	float y = GetTerrainHeight( x, z );
	lua_pushnumber( pL, y );
	return 1;
}

/*
===============
cLuaMgr
==============
*/

void cLuaMgr::LuaOpen( string filename )
{
	m_pLuaState = luaL_newstate();

	luaL_openlibs( m_pLuaState );
	RegisterFunc();

	LoadFile( filename );
	
}
void cLuaMgr::LuaClose()
{
	lua_close( m_pLuaState );
}
lua_State* cLuaMgr::GetLuaState()
{
	return m_pLuaState;
}

void cLuaMgr::LoadFile( string filename )
{
	if( luaL_loadfile( m_pLuaState, filename.c_str() ) ||
		lua_pcall( m_pLuaState, 0, 0, 0) ){
		ERRBOX( lua_tostring( m_pLuaState, -1 ) );
	}
}
void cLuaMgr::RegisterFunc()
{
	RegisterLib( m_pLuaState );
}

//////////////////////////////////////////////////////////////////////////
cLuaMgr* GetLuaMgr()
{
	return &gLuaMgr;
}

/*
==============
lua_functions
==============
*/

void PushVector( lua_State* pL, D3DXVECTOR3& vec3 )
{
	lua_newtable( pL ) ;

	lua_pushnumber( pL, vec3.x );
	lua_setfield( pL, -2, "x" );

	lua_pushnumber( pL, vec3.y );
	lua_setfield( pL, -2, "y" );

	lua_pushnumber( pL, vec3.z );
	lua_setfield( pL, -2, "z" );
}
void GetVector( lua_State* pL, const char* name, D3DXVECTOR3& vec3 )
{
	//assume that the vector is in table 
	//and the table in on the stack, its index is -1
	lua_getfield( pL, -1, name );
	
	lua_getfield( pL, -1, "x" );
	vec3.x = lua_tonumber( pL, -1 );
	lua_pop( pL, 1 );

	lua_getfield( pL, -1, "y" );
	vec3.y = lua_tonumber( pL, -1 );
	lua_pop( pL, 1 );

	lua_getfield( pL, -1, "z" );
	vec3.z = lua_tonumber( pL, -1 );
	lua_pop( pL, 1 );

	lua_pop( pL, 1 ) ;
}
void SetVector( lua_State* pL, const char* name, D3DXVECTOR3 vec3 )
{
	//assume that the vector is in table
	//and the table is on the stack, its index is -1
	lua_getfield( pL, -1, name );

	lua_pushnumber( pL, vec3.x );
	lua_setfield( pL, -2, "x" );

	lua_pushnumber( pL, vec3.y );
	lua_setfield( pL, -2, "y" );

	lua_pushnumber( pL, vec3.z );
	lua_setfield( pL, -2, "z" );

	lua_pop( pL, 1 );
}

void GetNumber( lua_State* pL, const char* name, float& n )
{
	//assume that the num is in the table
	//the table's index is -1
	lua_getfield( pL, -1, name );
	if( IsNumber( pL, -1 ) )
	{
		n = lua_tonumber( pL, -1 );
		lua_pop( pL, 1 );
	}
	else {
		ERRBOX( "GetNumber Failed\n" );
	}
}

void SetNumber( lua_State* pL, const char* name, float& n )
{
	//assume that the num is in the table
	//the table's index is -1
	lua_pushnumber( pL, n );
	lua_setfield( pL, -2, name );
}

void GetString( lua_State* pL, const char* name, string& str )
{
	//assume that the str is in the table
	//the table's index is -1
	lua_getfield( pL, -1, name );
	if( IsString( pL, -1 ) )
	{
		str = lua_tostring( pL, -1 );
		lua_pop( pL, 1 );
	}
	else{
		ERRBOX( "GetString Failed \n" );
	}
}

void SetString( lua_State* pL, const char* name, string& str )
{
	//assume that the str is in the table
	//the table's index is -1
	lua_pushstring( pL, str.c_str() );
	lua_setfield( pL, -2, name );
}

void GetBoolean( lua_State* pL, const char* name, bool& b )
{
	lua_getfield( pL, -1, name );
	if( IsBoolean( pL, -1 ) )
	{
		b = lua_toboolean( pL, -1 );
		lua_pop( pL, 1 );
	}
	else{
		ERRBOX( "GetBoolean Failed \n" ) ;
	}
}
void SetBoolean( lua_State* pL, const char* name, bool& b )
{
	lua_pushboolean( pL, b );
	lua_setfield( pL, -2, name );
}



bool IsTable( lua_State* pL, int idx )
{
	if( lua_istable( pL, idx ) == 0 )
		return false;
	return true;
}

bool IsNumber( lua_State* pL, int idx )
{
	if( lua_isnumber( pL, idx ) == 0 )
		return false;
	return true;
}

bool IsString( lua_State* pL, int idx )
{
	if( lua_isstring( pL, idx ) == 0 )
		return false;
	return true;
}

bool IsBoolean( lua_State* pL, int idx )
{
	if( lua_isboolean( pL, idx ) == 0 )
		return false;
	return true;
}








